﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OpenGL;

namespace Exhibition
{
	class ExhibitionBase
	{
		public GLTexture Floor;
		public double TOTAL_WIDTH;
		public double TOTAL_LENGTH;
		public const double W1A = 6.5;
		public const double W1B = 5;
		public const double W2A = 5.5;
		public const double W2B = 5.5;

		public const double W3A = 5.5;
		public const double W3B = 6.0;

		public const double HEIGHT = 5;
		public const double HEIGHT2 = 4;

		public List<Wall> Walls = new List<Wall>();

		public GLTexture WallTXT;
		public GLTexture FloorTXT;

		public ExhibitionBase()
		{
			Floor = new GLTexture("floor.jpg");
		}

		double P1LENGTH, P2LENGTH, P3LENGTH, P4LENGTH;

		public void BuildRoom(List<double> W, List<double> H)
		{
			WallTXT = new GLTexture("wall.jpg");
			FloorTXT = new GLTexture("floor.jpg");
			double DOOR_WIDTH = 2;
			double GAP = 0.5;
			TOTAL_WIDTH = W3A + W3B + 2;
			P1LENGTH = 6;
			P2LENGTH = W[5] + 2 * GAP;
			P3LENGTH = W[12] + 2 * GAP;
			P4LENGTH = W[15] + W[16] + DOOR_WIDTH + 4 * GAP;

			TOTAL_LENGTH = P1LENGTH + P2LENGTH + P3LENGTH + P4LENGTH;

			V3D FrontLeft = new V3D(-TOTAL_LENGTH / 2, 0, TOTAL_WIDTH / 2);
			V3D FrontRight = new V3D(TOTAL_LENGTH / 2, 0, TOTAL_WIDTH / 2);

			V3D BackLeft = new V3D(-TOTAL_LENGTH / 2, 0, -TOTAL_WIDTH / 2);
			V3D BackRight = new V3D(TOTAL_LENGTH / 2, 0, -TOTAL_WIDTH / 2);

			V3D P1 = BackLeft + V3D.Red * P4LENGTH;
			V3D P2 = FrontLeft + V3D.Red * P4LENGTH;
			V3D P3 = BackLeft + V3D.Red * (P4LENGTH + P3LENGTH);
			V3D P4 = FrontLeft + V3D.Red * (P4LENGTH + P3LENGTH);
			V3D P5 = BackLeft + V3D.Red * (P4LENGTH + P3LENGTH + P2LENGTH);
			V3D P6 = FrontLeft + V3D.Red * (P4LENGTH + P3LENGTH + P2LENGTH);

			//Left
			AddWall(0, FrontLeft, BackLeft, 0.1, HEIGHT);
			//Right
			AddWall(1, BackRight, FrontRight, 0.1, HEIGHT);

			//Back
			AddWall(2, BackLeft + V3D.Red * (GAP + DOOR_WIDTH), BackRight, 0.1, HEIGHT);
			//Back Door
			AddWall(3, BackLeft, BackLeft + V3D.Red * GAP, 0.1, HEIGHT);
			//Front
			AddWall(4, FrontLeft, FrontLeft + V3D.Red * (TOTAL_LENGTH - 3.5 - 1), 0.1, HEIGHT);
			//Front Door
			AddWall(5, FrontRight - V3D.Red * (2+GAP), FrontRight, 0.1, 5);

			AddWall(6, P1, P1 + V3D.Blue * W3A, 0.3, HEIGHT);
			AddWall(7, P2, P2 - V3D.Blue * W3B, 0.3, HEIGHT);

			AddWall(8, P3, P3 + V3D.Blue * W3A, 0.1, HEIGHT2);
			AddWall(9, P4, P4 - V3D.Blue * W3B, 0.1, HEIGHT2);

			AddWall(10, P5, P5 + V3D.Blue * W1A, 0.3, HEIGHT);
			AddWall(11, P6, P6 - V3D.Blue * W1B, 0.3, HEIGHT);

			//Front Door
			AddWall(12, FrontRight - V3D.Red * (2 + GAP) + (V3D.Green * 3), (V3D.Green * 3) + FrontRight - V3D.Red * (2 + GAP + DOOR_WIDTH), 0.1, HEIGHT - 3);
			//Back Door
			AddWall(13, BackLeft + V3D.Red * (GAP + DOOR_WIDTH) + (V3D.Green * 3), BackLeft + V3D.Red * GAP + (V3D.Green * 3), 0.1, HEIGHT - 3);
			Lights.Clear();
			for (int i = 0; i < 2; i++)
			{
				Lights.Add(new V3D(-10, 1, -5 + i * 10));
				Lights.Add(new V3D(-3.33, 1, -5 + i * 10));
				Lights.Add(new V3D(3.33, 1, -5 + i * 10));
				Lights.Add(new V3D(10, 1, -5 + i * 10));
			}
		}
		List<V3D> Lights = new List<V3D>();

		public void AddWall(int id, V3D p1, V3D p2, double w, double h)
		{
			Walls.Add(new Wall(id, p1, p2, w, h, WallTXT));
		}

		public void Draw()
		{
			GL.glDisable(GL.GL_LIGHTING);
			foreach (V3D L in Lights)
			{
				GL.glPushMatrix();
				GL.glTranslated(L.X, L.Y, L.Z);
				//GL.DrawSign();
				GL.glPopMatrix();
			}
			uint NL = 0;
			foreach(V3D L in Lights)
			{
				GL.SetLight(NL, (float)L.X, (float)L.Y, (float)L.Z, 0.1f, 0.1f, 0.1f);
				NL++;
			}

			GL.glEnable(GL.GL_LIGHTING);
			//GL.SetLight(4, 6, 2, 0, 0.2f, 0.2f, 0.2f);

			//glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, 1f, 0f, 1f);
			foreach (Wall W in Walls)
				W.Draw();

			GL.glPushMatrix();
			GL.glRotated(90, -1, 0, 0);
			FloorTXT.Draw(TOTAL_LENGTH, TOTAL_WIDTH, 3, 10);
			GL.glRotated(180, 1, 0, 0);
			GL.glTranslated(0, 0, -HEIGHT);
			WallTXT.Draw(TOTAL_LENGTH, TOTAL_WIDTH, 1, 10);
			GL.glPopMatrix();
		}

		public void GetVectors(int wid, bool bs, double wx, out V3D P, out V3D N)
		{
			V3D X = bs ? Walls[wid].P2 : Walls[wid].P1;
			V3D D = (Walls[wid].P2 - Walls[wid].P1).Unit * (bs ? -1 : 1);

			P = X + D * wx;
			N = D.RotY(-90);
		}
	}
}